﻿using BencodeNET.Objects;
using Furion;
using Furion.DependencyInjection;
using Mapster;
using Microsoft.AspNetCore.Http;
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace PrivateTracker.NET.Application
{
    public class AnnounceService : IAnnounceService, ITransient
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IPeerService _peerService;
        private readonly IClientService _clientService;
        public AnnounceService(IHttpContextAccessor httpContextAccessor, IPeerService peerService, IClientService clientService)
        {
            _httpContextAccessor = httpContextAccessor;
            _peerService = peerService;
            _clientService = clientService;
        }

        public async Task<BDictionary> GetAnnounceOutputAsync(AnnounceInput input)
        {
            //客户端验证
            bool isAllowClinet = await _clientService.IsAllowClinet();
            if (!isAllowClinet)
            {
                return await Task.FromResult<BDictionary>(new BDictionary() { { TrackerConsts.FailureKey, new BString("所使用的客户端不支持.") } });
            }
            if (string.IsNullOrWhiteSpace(input.Info_Hash) || input.Info_Hash.Length != 40)
            {
                return await Task.FromResult<BDictionary>(new BDictionary() { { TrackerConsts.FailureKey, new BString("不符合Tracker协议规范.") } });
            }
            if (!IPAddress.TryParse(input.Ip, out IPAddress ipAddress) || input.Port == 0)
            {
                return await Task.FromResult<BDictionary>(new BDictionary() { { TrackerConsts.FailureKey, new BString("不符合网络协议规范.") } });
            }
            if (string.IsNullOrWhiteSpace(input.Peer_Id) || input.Peer_Id.Length != 40)
            {
                return await Task.FromResult<BDictionary>(new BDictionary() { { TrackerConsts.FailureKey, new BString("客户端不符合规范.") } });
            }
            //删除超时汇报的种子
            if (input.Event == PeerEvent.Stopped)
            {
                await _peerService.DeletePeerAsync(input);
            }
            if (input.Event == PeerEvent.Completed)
            {
                //TODO 完成状态
            }
            //添加后返回所有
            var peers = await _peerService.AddPeerAsync(input);//await _torrentService.GetTorrentByHashInfoAsync(output.InfoHashByte, false, true);
            if (null != peers && peers.Any())
            {
                var total = Math.Min(peers.Count, input.Numwant.Value);
                // 判断当前 BT 客户端是否需要紧凑模式的数据。
                if (input.Compact == 1)
                {
                    var compactResponse = new byte[total * 6];
                    for (int index = 0; index < total; index++)
                    {
                        var peer = peers.ElementAt(index);
                        Buffer.BlockCopy(peer.ToBytes(), 0, compactResponse, index * 6, 6);
                    }
                    var keyValues = new BDictionary();
                    keyValues.Add(TrackerConsts.PeersKey, new BString(compactResponse));
                    // 客户端等待时间
                    keyValues.Add(TrackerConsts.IntervalKey, new BNumber((int)TimeSpan.FromSeconds(1800).TotalSeconds));
                    // 最小等待间隔
                    keyValues.Add(TrackerConsts.MinIntervalKey, new BNumber((int)TimeSpan.FromSeconds(1800).TotalSeconds));
                    // Tracker 服务器的 Id
                    keyValues.Add(TrackerConsts.TrackerIdKey, new BString("Tracker"));
                    // 已完成的 Peer 数量 
                    keyValues.Add(TrackerConsts.CompleteKey, new BNumber(100));//TODO
                    // 非做种状态的 Peer 数量
                    keyValues.Add(TrackerConsts.IncompleteKey, new BNumber(23));//TODO
                    return await Task.FromResult<BDictionary>(keyValues);
                }
                else
                {
                    var item = new BList();
                    for (int index = 0; index < total; index++)
                    {
                        var peer = peers.ElementAt(index);
                        var dic = new BDictionary
                            {
                                {TrackerConsts.PeerIdKey,new BString(input.Peer_Id)},
                                {TrackerConsts.Ip,new BString(input.Ip)},
                                {TrackerConsts.Port,new BNumber(input.Port) }
                            };
                        item.Add(dic);
                    }
                    return await Task.FromResult<BDictionary>(new BDictionary() { { TrackerConsts.PeersKey, item } });
                }
            }
            return await Task.FromResult<BDictionary>(new BDictionary() { });
        }
    }
}